﻿#region Header
// ------------------------ Licence / Copyright ------------------------
// 
// ScrumTable for Scrum Meeting Support
// Copyright © HSR - Hochschule für Technik Rapperswil
// All Rights Reserved
// 
// Author:
//  Michael Gfeller Silvan Gehrig Patrick Boos
// 
// ---------------------------------------------------------------------
#endregion

#region Usings

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using Microsoft.Surface.Presentation;
using Microsoft.Surface.Presentation.Input;
using ScrumTable.UI.View.Util;

#endregion

namespace ScrumTable.UI.View.WinTouch.Util
{

    /// <summary>
    /// DropDropUtil Util
    /// </summary>
    public class DrapDropUtil
    {
        private readonly IInputElement _element;
        public Point? ContactStart { get; set; }
        public DrapDropUtil(IInputElement element)
        {
            _element = element;
        }

        #region Methods
        //--------------------------------------------------------------------
        // Methods
        //--------------------------------------------------------------------

        /// <summary>
        /// InputDown
        /// </summary>
        /// <param name="e"></param>
        public void InputDown(InputEventArgs e)
        {
            ContactStart = e.Device.GetPosition(_element);
        }

        /// <summary>
        /// InputMove Event
        /// </summary>
        /// <typeparam name="TCursor"></typeparam>
        /// <typeparam name="TDataContext"></typeparam>
        /// <param name="e"></param>
        /// <param name="dragStartet"></param>
        public void InputMoved<TCursor, TDataContext>(InputEventArgs e, Action<bool> dragStartet)
            where TCursor : FrameworkElement, new()
            where TDataContext : FrameworkElement
        {
            if (!ContactStart.HasValue) return;

            var currentContact = e.Device.GetPosition(_element);
            var distX = Math.Abs(ContactStart.Value.X - currentContact.X);
            var distY = Math.Abs(ContactStart.Value.Y - currentContact.Y);

            if (distX > 10 || distY > 10)
            {
                
                Application.Current.MainWindow.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
                StartDrag<TCursor, TDataContext>(e, dragStartet);
                ContactStart = null;
            }
        }

        /// <summary>
        /// Starts a drop operation.
        /// </summary>
        /// <typeparam name="TCursor">type of the cursor</typeparam>
        /// <typeparam name="TDataContext">datacontext type</typeparam>
        /// <param name="inputArgs"></param>
        /// <param name="dragStartet">callback action after the drag has startet</param>
        public static void StartDrag<TCursor, TDataContext>(InputEventArgs inputArgs, Action<bool> dragStartet)
            where TCursor : FrameworkElement, new()
            where TDataContext : FrameworkElement
        {
            var findSource = inputArgs.OriginalSource as FrameworkElement;

            // Find the touched SurfaceListBoxItem object.
            var draggedElement = ViewElementUtils.FindVisualParent<TDataContext>(findSource);
            draggedElement = draggedElement ?? ViewElementUtils.FindVisualChild<TDataContext>(findSource);
            if (draggedElement == null)
                return;

            // Create the cursor visual.
            var cursorVisual = new TCursor
            {
                DataContext = draggedElement.DataContext
            };

            // Add a handler. This will enable the application to change the visual cues.
            //SurfaceDragDrop.AddTargetChangedHandler(cursorVisual, OnTargetChanged);

            // Create a list of input devices. Add the contacts that
            // are currently captured within the dragged element and
            // the current contact (if it isn't already in the list).
            var devices = new List<InputDevice> { inputArgs.Device };
            devices.AddRange(draggedElement.TouchesCapturedWithin.Where(contact => contact != inputArgs.Device));

            // Get the drag source object
            FrameworkElement dragSource = draggedElement;

            if (!IsContactActive(inputArgs))
                return;

            var cursor =
             SurfaceDragDrop.BeginDragDrop(
                 dragSource,                 // The SurfaceListBox object that the cursor is dragged out from.
                 draggedElement,             // The SurfaceListBoxItem object that is dragged from the drag source.
                 cursorVisual,               // The visual element of the cursor.
                 draggedElement.DataContext, // The data associated with the cursor.
                 devices,                    // The input devices that start dragging the cursor.
                 DragDropEffects.Move);      // The allowed drag-and-drop effects of the operation.


            
            dragStartet(cursor != null);
        }


        /// <summary>
        /// Checks if the device is active 
        /// </summary>
        /// <param name="inputArgs"></param>
        /// <returns></returns>
        public static bool IsContactActive(InputEventArgs inputArgs)
        {
            if (inputArgs.Device is MouseDevice)
            {
                ((MouseDevice)inputArgs.Device).Synchronize();
                if (((MouseDevice)inputArgs.Device).LeftButton == MouseButtonState.Released && ((MouseDevice)inputArgs.Device).Target != null)
                {
                    return false;
                }
            }
            return true;
        }
        #endregion

       
    }
}
